package com.fingard.dsp.bank.directbank.gzelink01;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.httpclient.NameValuePair;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.FailType;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.VerifyState;
import com.fingard.dsp.bank.directbank.bankInterface.ISMSRec;
import com.fingard.dsp.bank.directbank.gzelink01.util.EncryDecryUtils;
import com.fingard.dsp.bank.directbank.gzelink01.util.FormDateReportConvertor;
import com.fingard.dsp.bank.reqrespobj.single.ReqQrySingle;
import com.fingard.dsp.bank.reqrespobj.single.RetAtsSingle;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.dsp.bank.reqrespobj.smsrec.ReqSMSRec;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;

/**
 * 广银联快捷支付
 * 
 * 支付流程说明： 
 * step01: 
 * 			调用短信验证接口通过广银联平台发送验证码至用户手机； 
 * step02:
 * 			1、调用验证/鉴权接口校验短信验证码、订单号、用户开户行信息；
 * 			 2、身份校验成功后调用实时代扣接口进行扣款；
 * 
 * @date 2018/3/1
 * @author Cruise
 * @version 1.0
 */
public class GZELINK01SMSRec extends GZELINK01Base implements ISMSRec {
	@Override
	public RetAtsSingle d_9110_SMSRec(ReqSMSRec p_req9110) throws Exception {
		RetAtsSingle retAts = new RetAtsSingle(p_req9110.reqHeader);
		RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
		tmpRetDetail.failType = "";
		try {
			if (p_req9110.singleDetail.step.equals("01")) {
				// 第一步，短信验证
				ActSetItem actItem = getBankConfig().getActSetItem(p_req9110.singleDetail.recAct, "smsRecAuth");
				if (actItem == null) {
					tmpRetDetail.respCode = "0";
					tmpRetDetail.respInfo = "未找到账号["	+ p_req9110.singleDetail.recAct + "]商户配置信息!";
					tmpRetDetail.reqSeqID = p_req9110.singleDetail.askNumber;
					tmpRetDetail.transState = PaymentState.FAIL_Payment;
					tmpRetDetail.payInfoCode = "E9981";
					tmpRetDetail.failType = FailType.FailType2_System;
					retAts.writeRetDetail(tmpRetDetail);
					return retAts;
				}

				Map<String, String> postReqMap = new HashMap<String, String>();

				postReqMap.put("mhtOrderNo", p_req9110.singleDetail.askNumber + "dx");
				postReqMap.put("mobile", p_req9110.singleDetail.cellPhone);

				String encrptReqData = FormDateReportConvertor.postFormLinkReport(postReqMap);
				WriteBankLogLn2("广银联短信验证加密前数据明文:\r\n" + encrptReqData);

				String message1 = EncryDecryUtils.base64Encrypt("merchNo=" + actItem.merchantId);
				String message2 = EncryDecryUtils.encryptFromDESBase64(actItem.ownKeyPassword, encrptReqData);
				String message3 = EncryDecryUtils.base64Encrypt(EncryDecryUtils.md5(encrptReqData.trim() + "&" + actItem.saltKey));
				String message = message1 + "|" + message2 + "|" + message3;
				NameValuePair[] param = { new NameValuePair("message", message) };
				WriteBankLogStep2(getReqPostData(param));

				String tmpStrRet = sendAuthToBank(param, "smsRecVerify");

				if (tmpStrRet.split("\\|").length != 2) {
					String tmpEncryptRet = tmpStrRet.split("\\|")[1];
					String signature = tmpStrRet.split("\\|")[2];

					String originalMsg = EncryDecryUtils.decryptFromBase64DES(actItem.ownKeyPassword, tmpEncryptRet);
					originalMsg = URLDecoder.decode(originalMsg, "UTF-8").trim();
					WriteBankLogLn2("广银联短信验证响应数据明文:\r\n" + originalMsg);

					String originalSign = EncryDecryUtils.base64Decrypt(signature).trim();
					String localSign = EncryDecryUtils.md5(originalMsg + "&" + actItem.saltKey).trim();
					if (originalSign.equals(localSign)) {
						Map<String, String> respPostMap = getRespPostData(originalMsg);

						tmpRetDetail.respCode = "0";
						tmpRetDetail.respInfo = respPostMap.get("responseMsg");
						tmpRetDetail.reqSeqID = p_req9110.singleDetail.askNumber;

						String tmpRespCode = respPostMap.get("responseCode");
						if (tmpRespCode != null && "0000".equals(tmpRespCode)) {
							tmpRetDetail.respInfo = "已提交";
							tmpRetDetail.transState = PaymentState.SUCCESS;
							tmpRetDetail.payInfoCode = tmpRespCode;
						} else {
							tmpRetDetail.transState = PaymentState.FAIL;
							tmpRetDetail.failType = FailType.FailType2_System;
							tmpRetDetail.payInfoCode = tmpRespCode;
						}
					} else {
						tmpRetDetail.respCode = "-1";
						tmpRetDetail.respInfo = "短信验证响应数据本地验签失败";
					}
				} else {
					tmpRetDetail.respCode = "-1";
					tmpRetDetail.respInfo = EncryDecryUtils.base64Decrypt(tmpStrRet.split("\\|")[1]);
				}
			} else if (p_req9110.singleDetail.step.equals("02")) {
				// 第二步， 鉴权+实时代扣
				String authMerId = getBankConfig().getValueAsString("smsRecAuthMerId");
				if (StringHelper.isNullOrEmpty(authMerId)) {
					WriteBankLogLn2("未配置smsRecAuthMerId");
				}

				ActSetItem actItem = getBankConfig().getActSetItem(authMerId, "smsRecAuth");
				if (actItem == null) {
					tmpRetDetail.respCode = "0";
					tmpRetDetail.respInfo = "未找到账号:[" + authMerId + "]商户配置信息!";
					tmpRetDetail.reqSeqID = p_req9110.singleDetail.askNumber;
					tmpRetDetail.transState = PaymentState.FAIL_Payment;
					tmpRetDetail.payInfoCode = FailCode.E9981;
					tmpRetDetail.failType = FailType.FailType2_System;
					retAts.writeRetDetail(tmpRetDetail);
					return retAts;
				}

				Map<String, String> postReqMap = new HashMap<String, String>();

				postReqMap.put("mhtOrderNo", p_req9110.singleDetail.askNumber + "auth");
				postReqMap.put("idCardName", URLEncoder.encode(p_req9110.singleDetail.payName, "utf-8"));
				postReqMap.put("idCard", p_req9110.singleDetail.certNum);
				postReqMap.put("bankCardNum", p_req9110.singleDetail.payAct);
				postReqMap.put("mobile", p_req9110.singleDetail.cellPhone);
				postReqMap.put("msgCode", p_req9110.singleDetail.verifyCode);
				postReqMap.put("remarkes1", "");
				postReqMap.put("remarkes2", "");

				String plainMsg = FormDateReportConvertor.postFormLinkReport(postReqMap).trim();
				WriteBankLogLn2("广银联鉴权加密前数据明文:\r\n" + plainMsg);

				String message1 = EncryDecryUtils.base64Encrypt("merchNo=" + actItem.merchantId);
				String message2 = EncryDecryUtils.encryptFromDESBase64(actItem.ownKeyPassword, plainMsg);
				String message3 = EncryDecryUtils.base64Encrypt(EncryDecryUtils.md5(plainMsg + "&" + actItem.saltKey));
				String message = message1 + "|" + message2 + "|" + message3;

				NameValuePair[] param = {
						new NameValuePair("mode", getBankConfig().getValueAsString("modeType")),
						new NameValuePair("source", "01"),
						new NameValuePair("msgFlag", "2"),
						new NameValuePair("type", "02"),
						new NameValuePair("message", message) 
				};
				WriteBankLogStep2(getReqPostData(param));

				String tmpRetStr = sendAuthToBank(param, "smsRecAuth");

				if (tmpRetStr.split("\\|").length != 2) {
					String encryptMsg = tmpRetStr.split("\\|")[1];
					String signMsg = tmpRetStr.split("\\|")[2];

					String originalMsg = EncryDecryUtils.decryptFromBase64DES(actItem.ownKeyPassword, encryptMsg);
					originalMsg = URLDecoder.decode(originalMsg, "UTF-8").trim();
					WriteBankLogLn2("广银联鉴权响应业务参数明文:\r\n" + originalMsg);

					String originalSign = EncryDecryUtils.base64Decrypt(signMsg).trim();
					WriteBankLogLn2("广银联鉴权响应报文签名:\r\n" + originalSign);

					String localSign = EncryDecryUtils.md5(originalMsg + "&" + actItem.saltKey).trim();
					if (originalSign.equals(localSign)) {
						Map<String, String> respPostMap = getRespPostData(originalMsg);

						tmpRetDetail.respCode = "0";
						tmpRetDetail.respInfo = respPostMap.get("responseMsg");
						tmpRetDetail.reqSeqID = p_req9110.singleDetail.askNumber;

						String verifyState = "";
						String tmpRespCode = respPostMap.get("responseCode");
						if ("0000".equals(tmpRespCode)) {
							verifyState = VerifyState.SUCCESS;
							// 鉴权成功进入代扣
							WriteBankLogLn2("短信验证鉴权通过，进入短信扣款...");
							ActSetItem actItem1 = getBankConfig().getActSetItem(p_req9110.singleDetail.recAct, "smsRec");
							if (actItem1 == null || !FileHelper.existFile(actItem1.ownKeyStorePath)) {
								if (actItem1 == null) {
									throw new Exception("未找到账号:[" + p_req9110.singleDetail.recAct + "]商户配置信息");
								} else {
									throw new Exception("账号:[" + p_req9110.singleDetail.recAct	+ "]证书文件不存在");
								}
							}

							GZELINK01Header bankHeader = new GZELINK01Header();

							bankHeader.transCode = "100004";
							bankHeader.busiCode = getBankConfig().getMapValueByKey("RecBusiCode", "0");
							bankHeader.reqSeqNo = p_req9110.singleDetail.askNumber;
							bankHeader.totalNum = "1";
							bankHeader.totalAmt = p_req9110.singleDetail.payAmount;

							StringBuilder reqMsg = new StringBuilder();
							reqMsg = writePayRecSubmitMsg(reqMsg, actItem1,	bankHeader);

							reqMsg.append("<TRANS_DETAIL>");
							reqMsg.append("<SN>0001</SN>");
							reqMsg.append("<E_USER_CODE></E_USER_CODE>");

							String bankCode = getBankConfig().getMapValueByKey("BankCodeMapping", p_req9110.singleDetail.payBankCode);
							reqMsg.append("<BANK_CODE>" + bankCode + "</BANK_CODE>");

							String cardType = p_req9110.singleDetail.cardType;
							if ("1".equals(cardType)) {
								reqMsg.append("<ACCOUNT_TYPE>01</ACCOUNT_TYPE>");
							} else if ("2".equals(cardType)) {
								reqMsg.append("<ACCOUNT_TYPE>00</ACCOUNT_TYPE>");
							}

							reqMsg.append("<ACCOUNT_NO>" + p_req9110.singleDetail.payAct	+ "</ACCOUNT_NO>");
							reqMsg.append("<ACCOUNT_NAME>" + p_req9110.singleDetail.payName	+ "</ACCOUNT_NAME>");
							reqMsg.append("<PROVINCE></PROVINCE>");
							reqMsg.append("<CITY></CITY>");
							reqMsg.append("<BANK_NAME></BANK_NAME>");

							String isPrivate = p_req9110.singleDetail.isPrivate;
							if ("1".equals(isPrivate)) {
								reqMsg.append("<ACCOUNT_PROP>0</ACCOUNT_PROP>");
							} else {
								reqMsg.append("<ACCOUNT_PROP>1</ACCOUNT_PROP>");
							}

							reqMsg.append("<AMOUNT>"+ StringHelper.amountMultiply100(p_req9110.singleDetail.payAmount) + "</AMOUNT>");
							reqMsg.append("<CURRENCY>" + convertCurToBank(p_req9110.singleDetail.payCur) + "</CURRENCY>");
							reqMsg.append("<PROTOCOL></PROTOCOL>");
							reqMsg.append("<PROTOCOL_USERID></PROTOCOL_USERID>");
							reqMsg.append("<ID_TYPE></ID_TYPE>");
							reqMsg.append("<ID>" + p_req9110.singleDetail.certNum + "</ID>");
							reqMsg.append("<TEL>" + p_req9110.singleDetail.cellPhone + "</TEL>");
							reqMsg.append("<RECKON_ACCOUNT></RECKON_ACCOUNT>");
							reqMsg.append("<CUST_USERID></CUST_USERID>");
							reqMsg.append("<REMARK>" + p_req9110.singleDetail.memo + "</REMARK>");
							reqMsg.append("<REMARK1></REMARK1>");
							reqMsg.append("<REMARK2></REMARK2>");
							reqMsg.append("<REMARK3></REMARK3>");
							reqMsg.append("<REMARK4></REMARK4>");
							reqMsg.append("<ELE_BANKNO></ELE_BANKNO>");
							reqMsg.append("<ABS></ABS>");
							reqMsg.append("<PS></PS>");
							reqMsg.append("<USE></USE>");
							reqMsg.append("<CRE_VAL_DATE></CRE_VAL_DATE>");
							reqMsg.append("<CRE_CVN2></CRE_CVN2>");
							reqMsg.append("<ACC_PASS></ACC_PASS>");
							reqMsg.append("</TRANS_DETAIL>");
							reqMsg.append("</TRANS_DETAILS>");
							reqMsg.append("</BODY>");
							reqMsg.append("</GZELINK>");

							String signData = reqMsg.toString().replaceAll("<SIGNED_MSG></SIGNED_MSG>", "");
							WriteBankLogLn2("快捷支付签名原始数据:\r\n" + signData);
							String signature = signMsg(signData, actItem1);

							String reqData = reqMsg.toString().replaceAll("<SIGNED_MSG></SIGNED_MSG>", "<SIGNED_MSG>" + signature + "</SIGNED_MSG>");
							WriteBankLogStep2(reqData);

							String[] tmpRetStr1 = sendDataToGZE(reqData, bankFront.getUrl("smsRecPayQry"));
							if (tmpRetStr1[0].length() == 0) {
								WriteBankLogStep3(tmpRetStr1[1]);

								StringBuilder tmpSbMsg = new StringBuilder();
								XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpRetStr1[1], tmpSbMsg);

								if (tmpBkReader != null) {
									tmpRetDetail.respCode = "0";
									tmpRetDetail.respInfo = tmpBkReader.getFirstText("/GZELINK/INFO/ERR_MSG");

									String tmpRespCode1 = tmpBkReader.getFirstText("/GZELINK/INFO/RET_CODE");
									if ("0000".equals(tmpRespCode1)) {
										tmpRetDetail.reqSeqID = tmpBkReader.getFirstText("/GZELINK/INFO/REQ_SN");
										tmpRetDetail.respInfo = tmpBkReader.getFirstText("/GZELINK/BODY/RET_DETAILS/RET_DETAIL/ERR_MSG");

										String amount = tmpBkReader.getFirstText("/GZELINK/BODY/RET_DETAILS/RET_DETAIL/AMOUNT");
										if (StringHelper.hasAnyChar(amount)) {
											tmpRetDetail.transAmt = StringHelper.amountDivide100(amount);
										}

										tmpRetDetail.transState = StringHelper.joinNotEmpty("+",tmpRespCode1,tmpBkReader.getFirstText("/GZELINK/BODY/RET_DETAILS/RET_DETAIL/RET_CODE"));
										tmpRetDetail.payInfoCode = tmpBkReader.getFirstText("/GZELINK/BODY/RET_DETAILS/RET_DETAIL/RET_CODE");
									} else {
										tmpRetDetail.transState = tmpRespCode1;
										tmpRetDetail.payInfoCode = tmpRespCode1;
									}
								} else {
									tmpRetDetail.respCode = "-1";
									tmpRetDetail.respInfo = tmpSbMsg.toString();
								}
							} else {
								tmpRetDetail.respCode = "-1";
								tmpRetDetail.respInfo = tmpRetStr1[1];
							}
						} else {
							tmpRetDetail.transState = "auth+" + tmpRespCode;
							tmpRetDetail.payInfoCode = "auth+" + tmpRespCode;
							tmpRetDetail.failType = getBankConfig().getMapValueByKey("failTypeMapping", tmpRespCode);
							verifyState = VerifyState.FAIL;
						}
						
						String originalCode = respPostMap.get("responseCode");
	            		String originalInfo = respPostMap.get("responseMsg");
	            		String unifiedCode = getBankConfig().getMapValueByKey("AuthMapping", originalCode);
	            		String unifiedInfo = respPostMap.get("responseMsg");
	            		
	            		HashMap<String, String> authMapRet = new HashMap<String, String>();
	            		
	            		authMapRet.put("BankCode", p_req9110.reqHeader.bankCode);
	            		authMapRet.put("TransType", p_req9110.reqHeader.transType);
	            		if (StringHelper.hasAnyChar(p_req9110.singleDetail.cellPhone)) {
	            			authMapRet.put("ValidElement", "4");
	            		} else {
	            			authMapRet.put("ValidElement", "3");
	            		}
	            		authMapRet.put("OrderNo", p_req9110.singleDetail.askNumber + "auth");
	            		authMapRet.put("AuthName", p_req9110.singleDetail.payName);
	            		authMapRet.put("CertType", p_req9110.singleDetail.certType);
	            		authMapRet.put("CertNum", p_req9110.singleDetail.certNum);
	            		authMapRet.put("CardType", p_req9110.singleDetail.cardType);
	            		authMapRet.put("AccountNumber", p_req9110.singleDetail.payAct);
	            		authMapRet.put("CellPhone", p_req9110.singleDetail.cellPhone);
	            		authMapRet.put("AuthState", verifyState);
	            		authMapRet.put("UnifiedCode", unifiedCode);
	            		authMapRet.put("UnifiedInfo", unifiedInfo);
	            		authMapRet.put("OriganalCode", originalCode);
	            		authMapRet.put("OriganalInfo", originalInfo);
	            		authMapRet.put("ErrorMsg", unifiedInfo);
	            		authMapRet.put("FailType", tmpRetDetail.failType);
	            		authMapRet.put("AuthTime", Format.DateTimeFormat.format(Format.DateTime14Format.parse(respPostMap.get("responseTime"))));
	            		
	            		sendDataToMQ(authMapRet);
					} else {
						tmpRetDetail.respCode = "-1";
						tmpRetDetail.respInfo = "鉴权响应数据本地验签失败";
					}
				} else {
					tmpRetDetail.respCode = "-1";
					tmpRetDetail.respInfo = EncryDecryUtils.base64Decrypt(tmpRetStr.split("\\|")[1]);
				}
			} else {
				tmpRetDetail.respCode = "0";
				tmpRetDetail.respInfo = "未能识别的step：" + p_req9110.singleDetail.step;
				tmpRetDetail.reqSeqID = p_req9110.singleDetail.askNumber;
				tmpRetDetail.transState = PaymentState.FAIL_Payment;
				tmpRetDetail.payInfoCode = "E9981";
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}

		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}

	@Override
	public RetAtsSingle d_9146_QrySMSRec(ReqQrySingle p_req9146) throws Exception {
		RetAtsSingle retAts = new RetAtsSingle(p_req9146.reqHeader);
		RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();

		try {
			ActSetItem actItem = getBankConfig().getActSetItem(p_req9146.recAct, "smsRec");
			if (actItem == null || !FileHelper.existFile(actItem.ownKeyStorePath)) {
				tmpRetDetail.respCode = "-1";
				if(actItem == null){
					tmpRetDetail.respInfo = "未找到账号[" + p_req9146.recAct + "]批量商户配置信息";
				} else {
					tmpRetDetail.respInfo = "账号[" + p_req9146.recAct + "]证书文件不存在";
				}
				retAts.writeRetDetail(tmpRetDetail);
				return retAts;
			}

			GZELINK01Header bankHeader = new GZELINK01Header();

			bankHeader.transCode = "200001";
			bankHeader.reqSeqNo = p_req9146.askNumber;

			StringBuilder reqMsg = new StringBuilder();
			reqMsg = writePayRecQueryMsg(reqMsg, actItem, bankHeader, p_req9146.reqHeader.transSeqID);

			String signData = reqMsg.toString().replaceAll("<SIGNED_MSG></SIGNED_MSG>", "");
			WriteBankLogLn2("快捷支付查询待签名数据:\r\n" + signData);

			String signature = signMsg(signData, actItem);

			String reqData = reqMsg.toString().replaceAll("<SIGNED_MSG></SIGNED_MSG>", "<SIGNED_MSG>" + signature + "</SIGNED_MSG>");
			WriteBankLogStep2(reqData);

			String[] tmpRetStr = sendDataToGZE(reqData,	bankFront.getUrl("smsRecPayQry"));

			if (tmpRetStr[0].length() == 0) {
				WriteBankLogStep3(tmpRetStr[1]);

				StringBuilder tmpSbMsg = new StringBuilder();
				XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpRetStr[1],	tmpSbMsg);

				if (tmpBkReader != null) {
					tmpRetDetail.respCode = "0";
					tmpRetDetail.respInfo = tmpBkReader.getFirstText("/GZELINK/INFO/ERR_MSG");

					tmpRetDetail.reqSeqID = tmpBkReader.getFirstText("/GZELINK/BODY/QUERY_TRANS/QUERY_SN");
					if (StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)) {
						tmpRetDetail.reqSeqID = p_req9146.askNumber;
					}

					String tmpRespCode = tmpBkReader.getFirstText("/GZELINK/INFO/RET_CODE");
					if ("0000".equals(tmpRespCode)) {
						String amount = tmpBkReader.getFirstText("/GZELINK/BODY/RET_DETAILS/RET_DETAIL/AMOUNT");
						if (StringHelper.hasAnyChar(amount)) {
							tmpRetDetail.transAmt = StringHelper.amountDivide100(amount);
						}

						String tmpRetCode = tmpBkReader.getFirstText("/GZELINK/BODY/RET_DETAILS/RET_DETAIL/RET_CODE");
						String tmpErrMsg = tmpBkReader.getFirstText("/GZELINK/BODY/RET_DETAILS/RET_DETAIL/ERR_MSG");
						
						tmpRetDetail.transState = StringHelper.joinNotEmpty("+", tmpRespCode, tmpRetCode);
						tmpRetDetail.payInfoCode = tmpRetCode;
						
						if ("3999".equals(tmpRetCode)) {
							tmpRetDetail.payInfoCode = tmpErrMsg;
						}
						tmpRetDetail.respInfo = tmpErrMsg;
					} else {
						if ("3028".equals(tmpRespCode)) {
							tmpRetDetail.respCode = "-1";
						} else {
							tmpRetDetail.transState = tmpRespCode;
							tmpRetDetail.payInfoCode = tmpRespCode;
						}
					}
				} else {
					tmpRetDetail.respCode = "-1";
					tmpRetDetail.respInfo = tmpSbMsg.toString();
				}
			} else {
				tmpRetDetail.respCode = "-1";
				tmpRetDetail.respInfo = tmpRetStr[1];
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}

		retAts.writeRetDetail(tmpRetDetail);
		return retAts;
	}
}
